#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <types.h>
#include <utils.h>
#include <unistd.h>
#include <syserr.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include "dlist.h"
#include "softtimer.h"
#include "evtloop.h"
#include "object.h"
#include "printk.h"

static inline int soft_timer_in_loop(ev_loop_t *loop, struct soft_timer *t)
{
    struct object *obj;

    list_for_each_entry(obj, &loop->timer_head, entry)
    {
        struct soft_timer *_t = container_of(obj, struct soft_timer, obj);

        if (t == _t)
            return 1;
    }
    return 0;
}

int soft_timer_add(ev_loop_t *loop, struct soft_timer *t, const char *name,
                   soft_timer_cb_t cb, void *data)
{
    assert(cb);

    if (soft_timer_in_loop(loop, t))
        return -EEXIST;

    obj_init(&t->obj, OBJ_TYPE_NR, name);

    t->loop       = loop;
    t->timeout_cb = cb;
    t->repeat     = 0;
    t->data       = data;
    list_add_tail(&t->obj.entry, &loop->timer_head);
    return 0;
}
void soft_timer_del(struct soft_timer *t)
{
    ev__handle_stop(t);
    list_del(&t->obj.entry);
}

void soft_timer_start(struct soft_timer *t, u32 timeout, u32 repeat)
{
    assert(t && t->loop);

    ev__handle_stop(t);
    t->expires = hw_time() + timeout;
    t->repeat  = repeat;
    ev__handle_start(t);
}
void soft_timer_stop(struct soft_timer *t)
{
    ev__handle_stop(t);
}

static struct soft_timer *timer_expired(ev_loop_t *loop)
{
    struct object *obj;

    list_for_each_entry(obj, &loop->timer_head, entry)
    {
        struct soft_timer *t = container_of(obj, struct soft_timer, obj);

        if (ev__is_active(t) && time_after_eq(loop->time, t->expires))
            return t;
    }
    return NULL;
}

void soft_timer_service_run(ev_loop_t *loop)
{
    struct soft_timer *t;

    while ((t = timer_expired(loop)) != NULL)
    {
        if (t->repeat == 0)
            ev__handle_stop(t);
        else
            t->expires += t->repeat;

        t->timeout_cb(t->data);
    }
}

void soft_timer_dump(void)
{
    struct object *obj_loop, *obj_timer;

    printk("|==================================================================================|\r\n");
    printk("|            name   |            loop   |active| expires|  repeat|callback|    data|\r\n");
    printk("|==================================================================================|\r\n");

    list_for_each_entry(obj_loop, obj_head(OBJ_LOOP), entry)
    {
        ev_loop_t *loop = (ev_loop_t *)obj_loop;

        list_for_each_entry(obj_timer, &loop->timer_head, entry)
        {
            struct soft_timer *t = container_of(obj_timer, struct soft_timer, obj);

            printk("|%19s|%19s|%6d|%8x|%8x|%8x|%8x|\r\n",
                   obj_timer->name, obj_loop->name, ev__is_active(t),
                   t->expires, t->repeat, t->timeout_cb, t->data);
        }
    }

    printk("|==================================================================================|\r\n");
}
